package com.github.cyf.local;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.util.StreamUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

/**
 * @author chenyifan
 * @create 2025-06-04 9:53
 */
public class LocalDownloadUtil {
    /**
     * 下载文件（支持普通下载和断点续传）
     * @param filePath 文件完整路径
     * @param request HttpServletRequest对象
     * @param response HttpServletResponse对象
     * @throws IOException 文件操作异常
     * @throws FileNotFoundException 文件不存在异常
     */
    public static void downloadFile(String filePath, HttpServletRequest request, HttpServletResponse response) {

        // 1. 文件存在性检查
        File downloadFile = new File(filePath);
        if (!downloadFile.exists() || downloadFile.isDirectory()) {
            throw new DownloadException("文件不存在");
        }

        // 2. 设置响应头
        String fileName;
        try {
            fileName = URLEncoder.encode(downloadFile.getName(), StandardCharsets.UTF_8.name());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        // 设置内容处置头，强制浏览器下载而非直接打开
        response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
        // 支持断点续传
        response.setHeader(HttpHeaders.ACCEPT_RANGES, "bytes");

        // 3. 获取文件大小并处理范围请求
        long fileSize = downloadFile.length();
        long start = 0;
        long end = fileSize - 1; // 默认下载整个文件
        String rangeHeader = request.getHeader("Range");
        if (rangeHeader != null) {
            response.setStatus(HttpStatus.PARTIAL_CONTENT.value());
            // 解析范围请求格式（如："bytes=0-499"）
            String range = rangeHeader.replaceAll("bytes=", "");
            String[] rangeParts = range.split("-");
            start = Long.parseLong(rangeParts[0]);
            if (rangeParts.length > 1) {
                end = Long.parseLong(rangeParts[1]);
            }
            // 设置内容长度
            response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(end - start + 1));
        } else {
            // 普通下载，设置完整文件大小
            response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize));
        }

        // 4. 执行文件传输
        try (InputStream in = new BufferedInputStream(Files.newInputStream(downloadFile.toPath()));
             OutputStream out = response.getOutputStream()) {
            StreamUtils.copyRange(in, out, start, end);
            response.flushBuffer();
        } catch (IOException e) {
            throw new DownloadException("文件下载失败", e);
        }
    }
}
